package time;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期格式化辅助类
 */
@Slf4j
public final class DateUtil {

    public static final String PATTERN_MM_DD = "MM月dd日";
    public static final String PATTERN_MM_EN = "MM月";

    public static final String PATTERN_MM_DD_EN = "MM-dd";

    public static final String PATTERN_YYYY_MM_DD = "yyyy年MM月dd日";

    public static final String PATTERN_YYYY_MM_DD_EN = "yyyy-MM-dd";

    public static final String PATTERN_YYYY_MM_DD_HH_SS = "yyyy-MM-dd HH:mm:ss";

    public static final String PATTERN_YYYYMMDD = "yyyyMMdd";

    public static final String PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static final String PATTERN_M_D_EN = "M-d";

    public static final String PATTERN_M_DD_HH_MM_CH = "M月dd日HH:mm";

    public static final String[] weekWords = {"", "周一", "周二", "周三", "周四", "周五", "周六", "周日"};

    private DateUtil() {

    }

    public static String localDateTimeToString(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_SS);
        return dateTimeFormatter.format(localDateTime);
    }

    /**
     * 格式化日期
     */
    public static String format(Date date) {
        return format(date, PATTERN_YYYY_MM_DD);
    }

    public static String formatTime(Date date) {
        return format(date, PATTERN_YYYY_MM_DD_HH_SS);
    }


    public static Date parse(String dateString) throws ParseException {
        return DateUtils.parseDate(dateString, PATTERN_YYYY_MM_DD_HH_SS);
    }

    /**
     * 格式化日期
     */
    public static String format(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    public static Date parse(String dateString, String pattern) throws ParseException {
        return DateUtils.parseDate(dateString, pattern);
    }

    /**
     * 获取日期年份
     */
    public static Integer getYear(Date date) {
        return date.getYear();
    }

    public static Date now() {
        return new Date();
    }
    public static Date nowDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 当前周的周一
     */
    public static Date getCurrentWeekMonday(Date date) {
        return getCurrentWeekDay(date, 1);
    }
    /**
     * 当前周的周日
     */
    public static Date getCurrentWeekSunDay(Date date) {
        return getCurrentWeekDay(date, 7);
    }
    /**
     * 当前周几日期
     */
    public static Date getCurrentWeekDay(Date date, int targetWeek) {
        int week = getWeek(date);
        return DateUtils.addDays(date, targetWeek - week);
    }
    /**
     * 移动几周
     */
    public static Date moveWeek(Date date, int weeks) {
        return DateUtils.addDays(date, weeks * 7);
    }
    /**
     * 移动几月
     */
    public static Date moveMonth(Date date, int months) {
        return DateUtils.addMonths(date, months);
    }
    /**
     * 当月第一天
     */
    public static Date currentMonthOfFirstDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }
    /**
     * 当月最后一天
     */
    public static Date currentMonthOfLastDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(nowDate());
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        return calendar.getTime();
    }

    /**
     * 移动到当日的开始
     */
    public static Date move2DayStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
    /**
     * 移动当日结尾（精度秒）
     */
    public static Date move2DayEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    public static long getUnixTime(Date date) {
        return (date == null) ? 0 : date.getTime() / 1000;
    }

    public static boolean gt(Date a, Date b) {
        return a.compareTo(b) > 0;
    }

    public static boolean lt(Date a, Date b) {
        return a.compareTo(b) < 0;
    }

    public static Date min(Date a, Date b) {
        return gt(a, b) ? b : a;
    }

    public static int compareDay(Date a, Date b) {
        return ofDay(a).compareTo(ofDay(b));
    }

    public static int compareMonth(Date a, Date b) {
        return ofMonth(a).compareTo(ofMonth(b));
    }

    /**
     * 时分秒置为0
     */
    public static Date ofDay(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 月初，时分秒置为0
     */
    public static Date ofMonth(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 1-7(周一至周日)
     */
    public static int getWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w == 0) {
            w = 7;
        }
        return w;
    }

    public static String getWeekWord(Date date) {
        return getWeekWord(getWeek(date));
    }

    public static String getWeekWord(int week) {
        if (week < 0 ||
                week >= weekWords.length) {
            return null;
        } else {
            return weekWords[week];
        }
    }

    public static int getDayOfWeek(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
    }

    public static int getWeekOfMonth(Date time) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(time);
        return instance.get(Calendar.WEEK_OF_MONTH);
    }

    public static int getWeekOfYear(Date time) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(time);
        return instance.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * @Description 当前时间与零点的时间差
     **/
    public static Long getSecondsTobeforedawn() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }

    /**
     * 日期上加小时
     */
    public static Date addDateHour(Date date,Integer hours){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, hours);
        return cal.getTime();
    }

    /**
     * 日期上加 分钟
     */
    public static Date addDateMin(Date date,Integer minutes){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MINUTE, minutes);
        return cal.getTime();
    }

    public static Date addDateDay(Date date,Integer days){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, days);
        return cal.getTime();
    }
}
